/**
 * https://cnodejs.org/topic/5846b2883ebad99b336b1e06
 * https://github.com/NervJS/taro/issues/6078
 * 支付宝小程序报错：Uncaught TypeError: Cannot read property 'now' of undefined
 * 重写 lodash 库中需使用的方法
 */
/**
 * 防抖函数
 * @param {*} fn
 * @param {*} delay 毫秒
 * @returns
 */
export function debounce(fn, delay = 300) {
  let timer = null

  return (...args) => {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(this, args)
    }, delay)
  }
}

/**
 * 节流
 * @param {*} fn
 * @param {*} delay 毫秒
 */
export function throttle(fn, delay = 300) {
  var timer = null
  var startTime = Date.parse(new Date())

  return function(...args) {
    var curTime = Date.parse(new Date())
    var remaining = delay - (curTime - startTime)

    clearTimeout(timer)
    if (remaining <= 0) {
      fn.apply(this, args)
      startTime = Date.parse(new Date())
    } else {
      timer = setTimeout(fn.bind(this, ...args), remaining)
    }
  }
}

/**
 * 判断是否是基本数据类型
 * @param {*} value
 * @returns
 */
export function isPrimitive(value) {
  return (
    typeof value === 'string' || typeof value === 'number' || typeof value === 'symbol' || typeof value === 'boolean'
  )
}

/**
 * 判断是否是一个js对象
 * @param {*} value
 * @returns
 */
export function isObject(value) {
  return Object.prototype.toString.call(value) === '[object Object]'
}

/**
 * 浅拷贝
 * @param {*} value
 * @returns
 */
export function shallowClone(value) {
  let result

  if (isPrimitive(value)) {
    // 如果是基本数据类型，则直接返回
    return value
  } else if (Array.isArray(value)) {
    // 处理数组
    result = [...value]
  } else if (isObject(value)) {
    // 处理对象
    result = {...value}
  }

  return result
}

/**
 * 深拷贝
 * @param {*} value
 * @returns
 */
export function deepClone(value, deep = Infinity, objectStack = []) {
  if (deep <= 0 || objectStack.includes[value]) {
    // 深度超过限制 或 子对象内部引用了父级对象
    return null // 停止克隆
  }

  if (value instanceof Date) {
    return new Date(value)
  }

  if (Array.isArray(value)) {
    return value.map(item => (typeof item === 'object' ? deepClone(item, deep - 1, objectStack.concat([value])) : item))
  }

  const result = shallowClone(value)

  if (result && typeof result === 'object') {
    Object.entries(result).forEach(([k, v]) => {
      if (v && typeof v === 'object') {
        result[k] = deepClone(v, deep - 1, objectStack.concat([value]))
      }
    })
  }
  return result
}

/**
 * 拷贝一个值
 * @param {*} value
 * @param {*} isDeep 是否深拷贝
 */
export function clone(value, isDeep = false) {
  if (isDeep) {
    return deepClone(value)
  }
  return shallowClone(value)
}

/**
 * 获取随机数
 * @param {*} min
 * @param {*} max
 * @returns
 */
export function getRandom(min = 0, max = 255) {
  return Math.floor(Math.random() * (max - min + 1)) + min
}

/**
 * 获取价格区间展示文本
 * @param {*} min
 * @param {*} max
 */
export function getPriceAreaDesc(min, max) {
  let desc = ''

  if (min === max) {
    desc = `${min}元`
  } else if (!max) {
    desc = `${min}元以上`
  } else if (!min) {
    desc = `${max}元以下`
  } else {
    desc = `${min}-${max}元`
  }
  return desc
}

/**
 * 电话号码加密
 * @param {*} phoneNumber
 * @returns
 */
export function encryptPhoneNumber(phoneNumber) {
  if (!phoneNumber) {
    return phoneNumber
  }

  if (phoneNumber.length < 4) {
    return phoneNumber || ''
  } else if (phoneNumber.length >= 4 && phoneNumber.length <= 7) {
    return phoneNumber.slice(0, 3).padEnd(phoneNumber.length, '*')
  }
  return phoneNumber.slice(0, 3) + '****' + phoneNumber.slice(7)
}

/**
 * 获取当前日期+时间
 * @returns
 */
export function getCurrentFormattedTime() {
  const now = new Date()

  // 获取年份
  const year = now.getFullYear()

  // 获取月份并补零
  const month = String(now.getMonth() + 1).padStart(2, '0')

  // 获取日期并补零
  const date = String(now.getDate()).padStart(2, '0')

  // 获取小时数并补零
  const hours = String(now.getHours()).padStart(2, '0')

  // 获取分钟数并补零
  const minutes = String(now.getMinutes()).padStart(2, '0')

  // 获取秒数并补零
  const seconds = String(now.getSeconds()).padStart(2, '0')

  // 返回格式化后的时间
  return `${year}-${month}-${date} ${hours}:${minutes}:${seconds}`
}
